package com.stress.testing.plugin.javax.servlet.interceptor;

import com.stress.testing.common.StressTesting;
import com.stress.testing.common.TraceContext;
import com.stress.testing.common.TraceContextHolder;
import com.stress.testing.common.interceptor.AbstractInterceptor;

import javax.servlet.http.HttpServletRequest;
import java.lang.reflect.Method;
import java.util.Enumeration;
import java.util.UUID;

public class HttpServletServiceInterceptor extends AbstractInterceptor {
    @Override
    public void before(Method method, Object[] args, Object zuper, Object thiz) {
        if (!isValid(method, args)) {
            return;
        }

        TraceContext traceContext = TraceContextHolder.getTraceContext();
        if (traceContext == null) {
            traceContext = new TraceContext(getAgentConfig().getTracePropertyPrefix());
            TraceContextHolder.setTraceContext(traceContext);
        }

        HttpServletRequest httpServletRequest = (HttpServletRequest) args[0];
        Enumeration<String> headerNames = httpServletRequest.getHeaderNames();
        String tracePropertyPrefix = getAgentConfig().getTracePropertyPrefix();

        while (headerNames.hasMoreElements()) {
            String headerName = headerNames.nextElement();
            if (headerName.startsWith(tracePropertyPrefix) && !traceContext.hasProperty(headerName)) {
                traceContext.setProperty(headerName, httpServletRequest.getHeader(headerName));
            }
        }

        if (!traceContext.hasTraceID()) {
            traceContext.setTraceID(UUID.randomUUID().toString().replace("-", ""));
        }
    }

    private boolean isValid(Method method, Object[] args) {
        if (!StressTesting.enable(getAgentConfig(), getPluginConfig())) {
            return false;
        }

        Class<?>[] parameterTypes = method.getParameterTypes();
        if (parameterTypes == null || parameterTypes.length != 2) {
            return false;
        }

        Class<?> parameterType = parameterTypes[0];
        if (!parameterType.equals(HttpServletRequest.class)) {
            return false;
        }

        if (args == null || args.length == 0) {
            return false;
        }

        Object arg = args[0];

        if (arg == null) {
            return false;
        }

        if (!(arg instanceof HttpServletRequest)) {
            return false;
        }

        return true;
    }
}
